﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using MovieReviews.Controllers;
using MovieReview.Models;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace MovieReviews.Controller.Tests
{
    [TestClass()]
    public class UnitTest1
    {
        [TestMethod()]
        public void GetAllTest()
        {
            MovieController m = new MovieController();
            IEnumerable<MovieListing> all = m.GetAllListings();
            Assert.IsNotNull(all);
        }

        [TestMethod()]
        public void GetMovieByNameTestValidData()
        {
            MovieController m = new MovieController();
            String expected = "The Godfather";
            String actual;
            List<MovieListing> byName = m.GetMovieByName(expected).ToList();

            bool isEmpty = !byName.Any();
            if (isEmpty)
            {
                Assert.Fail();
            }
            else
            {
                foreach (MovieListing movie in byName)
                {
                    actual = movie.MovieName;
                    Assert.AreEqual(expected, actual);
                }
            }            
        }

        [TestMethod()]
        public void GetMovieByNameTestInvalidData()
        {
            MovieController m = new MovieController();
            String expected = "Bad Movie Name - Doesnt exist";
            List<MovieListing> byName = m.GetMovieByName(expected).ToList();
            bool isEmpty = !byName.Any();
            Assert.IsTrue(isEmpty);
        }

        [TestMethod()]
        public void GetMovieByUserTestValidData()
        {
            MovieController m = new MovieController();
            String expected = "Alice";
            String actual;
            List<MovieListing> byUser = m.GetMovieByUser(expected).ToList();

            bool isEmpty = !byUser.Any();
            if (isEmpty)
            {
                Assert.Fail();
            }
            else
            {
                foreach (MovieListing movie in byUser)
                {
                    actual = movie.Reviewer;
                    Assert.AreEqual(expected, actual);
                }
            } 
        }

        [TestMethod()]
        public void GetMovieByUserTestInvalidData()
        {
            MovieController m = new MovieController();
            String expected = "Bad User Name - Doesnt exist";
            List<MovieListing> byUser = m.GetMovieByUser(expected).ToList();
            bool isEmpty = !byUser.Any();
            Assert.IsTrue(isEmpty);
        }

        [TestMethod()]
        public void GetMovieByMovieAndUserTestValidData()
        {
            MovieController m = new MovieController();
            String actualMovie;
            String actualUser;
            String expectedMovie = "The Godfather";
            String expectedUser = "Alice";
            List<MovieListing> byMovieAndUser = m.GetMovieAndUser(expectedMovie, expectedUser).ToList();
            bool isEmpty = !byMovieAndUser.Any();
            if (isEmpty)
            {
                Assert.Fail();
            }
            else
            {
                foreach (MovieListing movie in byMovieAndUser)
                {
                    actualMovie = movie.MovieName;
                    actualUser = movie.Reviewer;
                    Assert.AreEqual(expectedMovie, actualMovie);
                    Assert.AreEqual(expectedUser, actualUser);
                }
            } 

        }

        [TestMethod()]
        public void GetMovieByMovieAndUserTestInvalidData()
        {
            MovieController m = new MovieController();
            String expectedMovie = "Bad Movie Name - Doesnt exist";
            String expectedUser = "Bad User Name - Doesnt exist";
            List<MovieListing> byMovieAndUser = m.GetMovieAndUser(expectedMovie, expectedUser).ToList();
            bool isEmpty = !byMovieAndUser.Any();
            Assert.IsTrue(isEmpty);
        }

        [TestMethod()]
        public void GetMovieByRatingTestValidData()
        {
            MovieController m = new MovieController();
            double expected = 8.0;
            double actual;
            List<MovieListing> byRating = m.GetMovieByRating(expected).ToList();

            bool isEmpty = !byRating.Any();
            if (isEmpty)
            {
                Assert.Fail();
            }
            else
            {
                foreach (MovieListing movie in byRating)
                {
                    actual = movie.Rating;
                    bool greaterThan = expected<=actual;
                    Assert.IsTrue(greaterThan);
                }
            }   
        }

        [TestMethod()]
        public void GetMovieByRatingTestInvalidData()
        {
            MovieController m = new MovieController();
            double expected = 19.0;
            List<MovieListing> byRating = m.GetMovieByRating(expected).ToList();
            bool isEmpty = !byRating.Any();
            Assert.IsTrue(isEmpty);
        }

        [TestMethod()]
        public void GetMovieByDateTestValidData()
        {
            MovieController m = new MovieController();
            DateTime expected = new DateTime(2008, 01, 01);
            DateTime actual;
            List<MovieListing> byDate = m.GetMovieByDate(expected).ToList();

            bool isEmpty = !byDate.Any();
            if (isEmpty)
            {
                Assert.Fail();
            }
            else
            {
                foreach (MovieListing movie in byDate)
                {
                    actual = movie.ReleaseDate;
                    bool greaterThan = expected <= actual;
                    Assert.IsTrue(greaterThan);
                }
            } 
        }

        [TestMethod()]
        public void GetMovieByDateTestInvalidData()
        {
            MovieController m = new MovieController();
            DateTime expected = new DateTime(2080,01,01);
            List<MovieListing> byDate = m.GetMovieByDate(expected).ToList();
            bool isEmpty = !byDate.Any();
            Assert.IsTrue(isEmpty);
        }

        [TestMethod()]
        public void DeleteListingTest()
        {
            MovieController m = new MovieController();
            String expectedMovie = "Django";
            String expectedUser = "Evan";
            m.DeleteListing(expectedMovie, expectedUser);
            List<MovieListing> byMovieAndUser = m.GetMovieAndUser(expectedMovie, expectedUser).ToList();
            bool isEmpty = !byMovieAndUser.Any();
            Assert.IsTrue(isEmpty);
        }

        [TestMethod()]
        public async Task PostAddListingTestValidData()
        {
            MovieController m = new MovieController();
            HttpResponseMessage response=new HttpResponseMessage();
            try
            {
                using (HttpClient client = new HttpClient())
                {
                    client.BaseAddress = new Uri("http://aliciabrowne.cloudapp.net/");                             // base URL for API Controller i.e. RESTFul service

                    // add an Accept header for JSON - preference for response 
                    client.DefaultRequestHeaders.
                        Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    MovieListing newMovie = new MovieListing { MovieName = "Django", Rating = 8.1, ReleaseDate = new DateTime(2011, 12, 25), Review = "Great movie", Reviewer = "Evan" };                
                    response = await client.PostAsJsonAsync("api/movie", newMovie);
                    Assert.IsTrue(response.IsSuccessStatusCode);
                    if (response.IsSuccessStatusCode)                                                       // 200 .. 299
                    {
                        Uri newStockUri = response.Headers.Location;
                        var listing = await response.Content.ReadAsAsync<MovieListing>();
                    }
                  
                }
            }
            catch
            {
                Assert.Fail();
            }  
        }

        [TestMethod()]
        public async Task PostAddListingTestInvalidData()
        {
            MovieController m = new MovieController();
            HttpResponseMessage response = new HttpResponseMessage();
            try
            {
                using (HttpClient client = new HttpClient())
                {
                    client.BaseAddress = new Uri("http://aliciabrowne.cloudapp.net/");                             // base URL for API Controller i.e. RESTFul service

                    // add an Accept header for JSON - preference for response 
                    client.DefaultRequestHeaders.
                        Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    MovieListing newMovie = new MovieListing { MovieName = "Django", Rating = 18.1, ReleaseDate = new DateTime(2011, 12, 25), Review = "Great movie", Reviewer = "Evan" };
                    response = await client.PostAsJsonAsync("api/movie", newMovie);
                    Assert.IsFalse(response.IsSuccessStatusCode);
                }
            }
            catch
            {
                Assert.Fail();
            }
        }

        [TestMethod()]
        public void PutUpdateListingTestValidData()
        {
            MovieController m = new MovieController();
            String expectedMovie = "Django";
            String expectedUser = "Evan";

            double expected = 7.1;
            double actual;

            MovieListing update = new MovieListing { MovieName = "Django", Rating = 7.1, ReleaseDate = new DateTime(2011, 12, 25), Review = "Great movie", Reviewer = "Evan" };
            m.PutUpdateListing(expectedMovie, expectedUser, update);
            List<MovieListing> byMovieAndUser = m.GetMovieAndUser(expectedMovie, expectedUser).ToList();
            bool isEmpty = !byMovieAndUser.Any();
            if (isEmpty)
            {
                Assert.Fail();
            }
            else
            {
                foreach (MovieListing movie in byMovieAndUser)
                {
                    actual = movie.Rating;
                    Assert.AreEqual(expected, actual);
                }
            } 
        } 

    }

}